import {
  forwardRef,
  useImperativeHandle,
  useState,
  useMemo,
  useCallback,
  useEffect,
  useRef,
} from 'react';
import { Dropdown, Menu, Button } from 'antd';
import { TextWidget } from '@inbiz/react';
import { useUpdateEffect } from 'ahooks';
import { InbizIcon, useEvents, isAuth } from '@inbiz/utils';
import { useField } from '@formily/react';
import api from './api';
import { RenderModal } from '@inbiz/render';
import './style.less';
import type { IConfig } from '../../designer/config';
import type { Ref, ReactElement, MouseEventHandler } from 'react';
import type { ButtonProps } from 'antd';
import type { inbiz } from '@inbiz/render';
import type {
  IModalEmit,
  IModalCallBackEvents,
  IModalRef,
} from '@inbiz/render';

export type IEformButtonGroup = {
  icon?: { type: string };
  iconPosition: 'left' | 'right';
  config: IConfig;
  title: {
    status: boolean;
    value: ReactElement;
  };
  emit?: {
    (type: 'onClick', btnType: 'btn' | 'subBtn', item: object): void;
    (type: 'onOpenChange', open: boolean): void;
  } & IModalEmit;
  disabled?: boolean;
  placement: 'bottom' | 'bottomLeft' | 'bottomRight' | 'top' | 'topLeft' | 'topRight';
  inbiz: inbiz;
  className?: string;
  callBackEvents: {
    onCreateModel: <T extends ISubModalData>(data: T) => Promise<T>;
  } & IModalCallBackEvents;
};
export type IOperation = Exclude<IConfig['operation'], undefined>['list'][number] & {
  danger?: boolean;
  disabled?: boolean;
};

type ISubModalData = {
  title: string | ReactElement;
  openType: IOperation['openType'];
  page: IOperation['page'];
  footer: Exclude<IConfig['subwindow'], undefined>['list'];
} & Omit<Exclude<IConfig['subwindow'], undefined>, 'list'>;
function EformButtonGroup(
  {
    title,
    icon,
    iconPosition,
    config,
    emit,
    callBackEvents,
    inbiz,
    placement,
    ...other
  }: IEformButtonGroup,
  ref: Ref<ReturnType<typeof api>>,
) {
  // 是否显示title
  const isTitile = useMemo(() => title.status, [title.status]);
  // 弹框ref
  const modalRef = useRef<IModalRef>();
  // 所有事件的集合
  const [configEvents] = useEvents(callBackEvents, emit);
  const field = useField();
  // 在表格中时, 获取表格的id, 不存在是为空
  const tableid = useMemo(() => {
    return field.address.segments.find((item) => {
      return inbiz(item as string)?.getField().data?.componentType === 'Table' ? item : undefined;
    }) as string | undefined;
  }, []);
  const [disabled, $disabled] = useState(other.disabled);
  const [operation, $operation] = useState<IOperation[]>();
  // 弹框内容数据
  const [subModelOption, $subModelOption] = useState({} as ISubModalData);
  useEffect(() => {
    $operation(
      (config.operation?.list || []).filter(({ flag }) =>
        //@ts-ignore 根据权限设置按钮数据
        isAuth(inbiz.auth, config.operation?.auth, flag),
      ),
    );
  }, [config.operation?.list]);

  useUpdateEffect(() => {
    $disabled(other.disabled);
  }, [other.disabled]);

  // 触发点击事件
  const handleClick = useCallback(
    async (item: IOperation) => {
      if (item.disabled) {
        return;
      }
      emit?.('onClick', 'btn', item);
      if (item.type === 'custom') {
        // 处理弹框数据
        const subModalData: ISubModalData = {
          title: item.windowName!,
          openType: item.openType,
          page: item.page?.split(',')?.[0],
          position: config.subwindow?.position,
          width: config.subwindow?.width,
          height: config.subwindow?.height,
          footer: config.subwindow?.list?.filter((subItem) => subItem.parent === item.id),
          showType: config.subwindow?.showType!,
        };
        if (subModalData.page) {
          const result = (await configEvents.current.onCreateModel?.(subModalData)) || subModalData;
          $subModelOption(result);
          setTimeout(() => {
            modalRef.current?.onOpen({
              data: { parentButton: result },
              id: result.page!,
              pageId: result.page!,
              queryData: {},
            });
          }, 0);
        }
      } else if (tableid) {
        inbiz(tableid)?.triggerOperation?.({
          actionType: item.type,
          openMode: item.openType,
          windowName: item.windowName,
        });
      }
    },
    [config.subwindow, emit, tableid],
  );
  const menu = useMemo(() => {
    const showType = config.operation?.showType || 1;
    const items =
      operation?.map((item) => {
        return {
          key: item.id,
          danger: item.danger,
          disabled: item.disabled,
          className: item.separator ? 'borderBottom' : '',
          label: (
            <ButtonGroupItem
              onClick={() => handleClick(item)}
              iconPosition="left"
              icon={showType != 1 ? item.icon : undefined}
              title={showType != 2 ? item.name : undefined}
            />
          ),
        };
      }) || [];
    return <Menu items={isTitile ? items : items.slice(1)} />;
  }, [operation, config.operation?.showType, isTitile]);

  const updateOperation = useCallback((flag: any, data: IOperation) => {
    // 通过标识更新指定按钮的的状态
    $operation((list) => {
      return list?.map((item) => {
        if (item.flag === flag) {
          return {
            ...item,
            ...data,
          };
        } else {
          return item;
        }
      });
    });
  }, []);
  const [trigger, $trigger] = useState<('click' | 'hover' | 'contextMenu')[]>(['click']);

  // 对外暴露的方法
  useImperativeHandle(
    ref,
    () => ({
      ...api(configEvents, {
        $disabled,
        updateOperation,
        $trigger,
        modalRef,
        operation,
        triggerClick: (flag: string) => {
          const item = operation?.find((item) => item.flag === flag);
          if (item) {
            handleClick(item);
          }
        },
      }),
    }),
    [operation],
  );

  const handleOpenChange = useCallback((open: boolean) => emit?.('onOpenChange', open), []);

  const footer = useMemo(() => {
    subModelOption.openType;
    return (
      subModelOption.footer?.map((item) => {
        return {
          children: subModelOption.showType != 2 ? item.name : undefined,
          ...(item as unknown as ButtonProps), // 通过扩展代码添加的的额外的属性
          type:
            subModelOption.openType === 'current'
              ? 'text'
              : item.type === 'save'
                ? 'primary'
                : item.type,
          icon:
            subModelOption.showType != 1 && item?.icon?.type ? (
              <InbizIcon type={item.icon?.type} />
            ) : undefined,
          onClick: (e) => {
            emit?.('onClick', 'subBtn', item);
            // @ts-ignore
            item.onClick?.(e);
            if (item.type === 'save') {
              modalRef.current?.submit();
            }
            if (item.type === 'cancel') {
              modalRef.current?.onClose();
            }
          },
        } as ButtonProps;
      }) || []
    );
  }, [subModelOption.footer]);

  const titileButton = useMemo(() => {
    return (
      !isTitile && (
        <Button
          type="default"
          disabled={operation?.[0]?.disabled}
          danger={operation?.[0]?.danger}
          onClick={() => handleClick(operation?.[0]!)}
        >
          {typeof operation?.[0]?.name === 'string' ? (
            <TextWidget>{operation[0]?.name}</TextWidget>
          ) : (
            operation?.[0]?.name
          )}
        </Button>
      )
    );
  }, [operation, isTitile, handleClick]);

  return (
    <>
      <div className={`${isTitile ? '' : 'eformButtonGroupButtons'}  iconPosition_${iconPosition}`}>
        {iconPosition == 'right' && titileButton}
        <Dropdown
          trigger={trigger}
          overlay={menu}
          disabled={disabled}
          overlayClassName={`eformButtonGroupOverlay ${other.className ? other.className + 'GroupOverlay' : ''
            }`}
          onVisibleChange={handleOpenChange}
          placement={placement}
        >
          {isTitile ? (
            <div className={`eformButtonGroupBox ${title?.value ? 'padding_15' : 'padding_10'}`}>
              <ButtonGroupItem
                iconPosition={iconPosition}
                title={isTitile ? title?.value : ''}
                icon={icon}
              />
            </div>
          ) : (
            <Button type="default" className="iconBtn" icon={<InbizIcon type={icon?.type!} />} />
          )}
        </Dropdown>
        {iconPosition == 'left' && titileButton}
      </div>
      <RenderModal
        title={
          typeof subModelOption.title === 'string' ? (
            <TextWidget>{subModelOption.title}</TextWidget>
          ) : (
            subModelOption.title
          )
        }
        className={`${other.className ? other.className + 'Modal' : ''} eformButtonGroupModal`}
        width={subModelOption.width}
        height={subModelOption.height}
        inbiz={inbiz}
        emit={emit!}
        callBackEvents={configEvents}
        ref={modalRef}
        cancel={false}
        submit={false}
        footer={footer}
        footerPosition={subModelOption.position}
        modalType={subModelOption.openType || 'modal'}
      />
    </>
  );
}

export default forwardRef(EformButtonGroup);

function ButtonGroupItem({
  iconPosition,
  icon,
  title,
  borderBottom,
  onClick,
}: {
  iconPosition: 'left' | 'right';
  icon?: { type: string };
  title?: ReactElement | string;
  borderBottom?: boolean;
  onClick?: MouseEventHandler<HTMLAnchorElement>;
}) {
  return (
    <a
      className={`buttonGroupItem ${(title && iconPosition) || ''} ${borderBottom ? 'borderBottom' : ''
        }`}
      onClick={onClick}
    >
      {iconPosition === 'left' && icon?.type && (
        <InbizIcon type={icon.type} className="buttonIcon" />
      )}
      {title && (typeof title === 'string' ? <TextWidget>{title}</TextWidget> : title)}
      {iconPosition === 'right' && icon?.type && (
        <InbizIcon type={icon?.type} className="buttonIcon" />
      )}
    </a>
  );
}
